#include "service_player.h"
#include "service_network.h"
#include "player_controller.h"
#include "service_favorites.h"
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>

// 定义全局变量的实体
pid_t g_background_download_pid = -1;

//定义一个临时保存收藏视频的地址
#define FAVORITE_PLAYBACK_FILE "/tmp/favorite_playback.mp4"



//定义全局变量播放列表
Playlist playlist; 

//初始化播放列表
void playlist_init()
{
    playlist.current_index = -1;
    playlist.total_videos = 0;
    playlist.head_index = 0;
    //初始化文件名
    for (int i = 0; i < MAX_HISTORY_SIZE; i++)
    {
        //i是用来替代这个文件的编号
        snprintf(playlist.files[i],sizeof(playlist.files[i]),VIDEO_FILE_TEMPLATE,i);
    }
    
}

//封装一个接口可用于刷新和初始化播放
static void start_new_session()
{
    printf("加载(刷新)中，请稍候...\n");

    //初始化播放列表结构体
    playlist_init();

    
    // 获取第一个视频URL
    char* first_url = get_new_video_url();
    if (first_url == NULL) {
        printf("启动失败: 获取第一个视频URL失败。\n");
        return;
    }

    //将第一个视频url存入链表
    strncpy(playlist.urls[0],first_url,sizeof(playlist.urls[0]));


    pid_t pid = fork();
    if (pid == 0) { // 子进程
        char cmd[2048];
        //下载到固定的临时文件保存
        snprintf(cmd, sizeof(cmd), "curl -sLk '%s' -o %s 2>/tmp/curl_init.log", first_url, CURRENT_VIDEO_FILE);
        execlp("sh", "sh", "-c", cmd, NULL);
        perror("execlp for initial curl failed");
        exit(1);
    }
    free(first_url);
}


// 初始化第一个视频播放
void service_play_init()
{
    start_new_session();
}

// 检查初始视频是否已下载完成
bool service_player_is_initial_video_ready(void) {
    struct stat st;
    return (stat(CURRENT_VIDEO_FILE, &st) == 0 && st.st_size > 1024);
}

// 播放已下载好的初始视频，并触发预加载
void service_player_play_initial_video(void) {
    printf("初始视频已就绪，开始播放。\n");

    //更新播放列表的指针和历史总数
    playlist.current_index = 0;
    playlist.total_videos = 1;

    //播放我们下载好的第一个视频依旧取巧改名字
    rename(CURRENT_VIDEO_FILE,playlist.files[0]);
    //播放第一个视频
    player_video(playlist.files[0]);



    printf("---------------------");
    update_favorite_button_status();


    //加载下一个视频
    preload_next_video();
}

// 在后台预加载下一个视频
void preload_next_video() {
    // 如果上一个下载任务还在跑，先停掉
    if (g_background_download_pid > 0) {
        kill(g_background_download_pid, SIGKILL);
    }

    // 获取新视频URL
    char* new_url = get_new_video_url();
    if (new_url == NULL) {
        printf("预加载失败: 获取新URL失败。\n");
        return;
    }

    //决定存储下一个视频的位置(动态计算)
    int next_location = (playlist.head_index + playlist.total_videos)%MAX_HISTORY_SIZE;

    //记录url
    strncpy(playlist.urls[next_location],new_url,sizeof(playlist.urls[next_location]));

    // 创建一个子进程去执行下载任务
    g_background_download_pid = fork();
    if (g_background_download_pid < 0) {
        perror("fork for preload failed");
        free(new_url);
        return;
    }

    if (g_background_download_pid == 0) { // 子进程: 执行下载
        char download_cmd[2048];
        //添加重定向把标准出错输出到curl.log
        snprintf(download_cmd, sizeof(download_cmd), 
                 "curl -sLk '%s' -o %s 2>/tmp/curl.log", 
                 new_url, playlist.files[next_location]);
        
        // 使用execlp来执行，更干净
        execlp("sh", "sh", "-c", download_cmd, NULL);
        // 如果execlp执行失败，下面的代码才会运行
        perror("execlp for curl failed");
        exit(1); 
    }

    // 父进程: 不等待子进程，立即返回，让下载在后台进行
    printf("已在后台开始预加载下一个视频...\n");
    free(new_url);
}


// 播放下一个视频（上滑功能）
bool service_play_next()
{

    //播放下一个视频有两种情况一个是加载新的，一个播放历史
    int next_index = playlist.current_index + 1;
    //下一个视频不在历史记录里面要创建
    if (next_index >= playlist.total_videos)
    {
        //计算下一个视频位置并且查看他状态
        int next_location = (playlist.head_index + playlist.total_videos)% MAX_HISTORY_SIZE;
        //判断状态(是否准备完毕)
        // 检查预加载的视频文件是否已准备好
        //使用文件状态结构体保存文件当前状态
        struct stat st;
        if (stat(playlist.files[next_location], &st) != 0 || st.st_size < 1024) 
        { // 小于1KB也认为无效
            printf("下一个视频还没准备好。\n");
            // 直接返回失败状态
            return false; 
        }
        //创建新的视频后需要更新视频总数
        if (playlist.total_videos < MAX_HISTORY_SIZE)
        {
            playlist.total_videos++;
        }else{
            //这是当前已经满了历史最大值的情况，移动头指针
            playlist.head_index = (playlist.head_index + 1)% MAX_HISTORY_SIZE;
        }
        
    }
    

    // 停止当前播放
    player_stop();
    
    //不在继续增加下一个当前视频的下标了，最大值就是历史记录的最大值-1
    if (playlist.current_index < MAX_HISTORY_SIZE - 1) {
        playlist.current_index++;
    }

    //计算当前下标视频的地址
    int current_location = (playlist.head_index + playlist.current_index)%MAX_HISTORY_SIZE;

    //播放当前的视频
    player_video(playlist.files[current_location]);

    printf("---------------------");
    update_favorite_button_status();
    
    // 立即开始为再下一个视频做准备！
    preload_next_video();

    return true;
}


//修改返回值判断成功失败刷新
int service_play_prev()
{   
    // 检查有没有上一个视频
    if (playlist.current_index <= 0)
    {
        printf("没有历史记录。\n");
        //停止当前的所以进程直接刷新
        player_stop();
        start_new_session();

        return 2;//返回二表示刷新
    }

    //有历史的情况
    //停止当前视频的播放
    player_stop();
    //下标前移指向上一个视频
    playlist.current_index--;

    //计算播放视频的位置
    int current_location = (playlist.head_index+playlist.current_index)%MAX_HISTORY_SIZE;
    player_video(playlist.files[current_location]);


    printf("---------------------");
    update_favorite_button_status();
    
    //有上一个视频的话返回1表示播放上一个视频成功
    return 1;
}

//收藏服务
void service_player_favorite_current_video(void) {
    if (playlist.current_index < 0) {
        printf("错误: 没有正在播放的视频。\n");
        return;
    }

    // 计算当前视频在环形缓冲区中的物理位置
    int current_physical_slot = (playlist.head_index + playlist.current_index) % MAX_HISTORY_SIZE;
    const char* current_url = playlist.urls[current_physical_slot];

    // 调用独立的收藏服务来处理
    service_favorite_add(current_url);
}

//实现重播功能
void service_player_replay_current(void)
{
    printf("请求重播当前视频...\n");

    // 安全检查：确保我们有一个合法的当前视频索引
    if (playlist.current_index < 0 || playlist.current_index >= playlist.total_videos) {
        printf("没有有效的当前视频可以重播。\n");
        // 在这种情况下，也许我们应该加载一个新视频？
        // 为了简单，我们暂时什么都不做。
        return;
    }

    // 在启动新播放前，先确保清理掉任何可能残留的旧进程
    player_stop();

    // 计算当前视频在环形缓冲区中的物理位置
    int current_physical_slot = (playlist.head_index + playlist.current_index) % MAX_HISTORY_SIZE;
    
    // 获取文件路径
    const char* video_to_play = playlist.files[current_physical_slot];
    printf("正在重播: %s\n", video_to_play);

    // 调用底层的播放器
    player_video(video_to_play);
}


//播放收藏的视频
void service_player_start_favorite_playback(const char* favorite_url) {
    if (favorite_url == NULL) return;
    
    printf("准备播放收藏视频: %s\n", favorite_url);
    
    // 这个函数只负责一件事：启动后台下载
    pid_t pid = fork();
    if (pid == 0) { // 子进程
        char cmd[2048];
        // 将收藏的视频下载到专门的临时文件中
        snprintf(cmd, sizeof(cmd), "curl -sLk '%s' -o %s 2>/tmp/curl_fav.log", favorite_url, FAVORITE_PLAYBACK_FILE);
        execlp("sh", "sh", "-c", cmd, NULL);
        exit(1);
    }
}

//检查收藏视频是否已经下载完毕
bool service_player_is_favorite_video_ready(void) {
    struct stat st;
    return (stat(FAVORITE_PLAYBACK_FILE, &st) == 0 && st.st_size > 1024);
}

//播放当前收藏的视频
void service_player_play_favorite_video(const char* favorite_url) {
    printf("收藏视频已就绪，开始播放并重置历史。\n");
    
    // 重置播放列表
    playlist_init();
    
    // 将这个收藏的视频作为新的“第一个”视频
    playlist.current_index = 0;
    playlist.total_videos = 1;
    strncpy(playlist.urls[0], favorite_url, sizeof(playlist.urls[0]) - 1);
    rename(FAVORITE_PLAYBACK_FILE, playlist.files[0]);
    
    // 播放
    player_video(playlist.files[0]);
    
    //立即开始为它的“下一个”视频做预加载
    preload_next_video();
}